VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
  Persistable = 0  'NotPersistable
  DataBindingBehavior = 0  'vbNone
  DataSourceBehavior  = 0  'vbNone
  MTSTransactionMode  = 0  'NotAnMTSObject
END
Attribute VB_Name = "IOperation"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit

Private Type typeOperation
 '///currently available types:
 '":=", "+", "-", "*", "/"
 '">", "<", "=", ">=", "<=", "<>"
 sType As String
End Type

Private m_t As typeOperation

Friend Sub CloneFrom(t As typeOperation)
m_t = t
End Sub

Friend Function Clone() As IOperation
Dim obj As New IOperation
obj.CloneFrom m_t
Set Clone = obj
End Function

Friend Property Get OperationType() As String
OperationType = m_t.sType
End Property

Friend Property Let OperationType(ByVal s As String)
m_t.sType = s
End Property

Friend Function Apply(ByVal objTarget As iValue, ByVal objConst As iValue, ByVal objConst2 As iValue) As iValue
On Error Resume Next
Dim obj As iValue
Dim n As Long
'///
Debug.Assert Not objTarget Is Nothing
If objConst Is Nothing Then Set objConst = New iValue
If objConst2 Is Nothing Then Set objConst2 = New iValue
'///
Select Case m_t.sType
'Case vbNullString '???
' Set obj = New iValue
Case ":="
 Set obj = objConst.Clone
Case "+"
 Set obj = objTarget.Clone
 obj.OperatorPlusEqual objConst
Case "-"
 Set obj = objTarget.Clone
 obj.OperatorMinusEqual objConst
Case "*"
 Set obj = objTarget.Clone
 obj.OperatorTimesEqual objConst
Case "/"
 Set obj = objTarget.Clone
 obj.OperatorDivideEqual objConst
Case "<"
 Set obj = New iValue
 obj.FromCurrency ((objTarget.Compare(objConst) And &H1&) <> 0) And 1&
Case "="
 Set obj = New iValue
 obj.FromCurrency ((objTarget.Compare(objConst) And &H2&) <> 0) And 1&
Case ">"
 Set obj = New iValue
 obj.FromCurrency ((objTarget.Compare(objConst) And &H4&) <> 0) And 1&
Case "<="
 Set obj = New iValue
 obj.FromCurrency ((objTarget.Compare(objConst) And &H3&) <> 0) And 1&
Case ">="
 Set obj = New iValue
 obj.FromCurrency ((objTarget.Compare(objConst) And &H6&) <> 0) And 1&
Case "<>"
 Set obj = New iValue
 obj.FromCurrency ((objTarget.Compare(objConst) And &H5&) <> 0) And 1&
Case "Abs"
 Set obj = objTarget.Clone
 obj.OperatorAbs
Case "Mod"
 Set obj = objTarget.Clone
 obj.OperatorModEqual objConst
Case "=Mod"
 Set obj = objTarget.Clone
 obj.OperatorModEqual objConst2
 obj.FromCurrency ((obj.Compare(objConst) And &H2&) <> 0) And 1&
Case "<>Mod"
 Set obj = objTarget.Clone
 obj.OperatorModEqual objConst2
 obj.FromCurrency ((obj.Compare(objConst) And &H5&) <> 0) And 1&
Case "^"
 Set obj = objTarget.Clone
 If Not obj.OperatorExpEqual(objConst) Then Set obj = Nothing
Case "Exp"
 Set obj = objConst.Clone
 If Not obj.OperatorExpEqual(objTarget) Then Set obj = Nothing
Case "Log"
 Set obj = objConst.Clone
 If Not obj.OperatorLogEqual(objTarget) Then Set obj = Nothing
Case "Log2"
 Set obj = objTarget.Clone
 If Not obj.OperatorLogEqual(objConst) Then Set obj = Nothing
Case "IsPrime", "IsNotPrime"
 If m_t.sType = "IsPrime" Then n = 1 Else n = 0
 Set obj = objTarget.Clone
 If obj.ConvertTo(IValue_Integer) Then
  Err.Clear
  If IsPrime(obj.ToDouble) Then
   If Err.Number = 0 Then
    obj.FromCurrency n
   Else
    obj.FromCurrency 1 - n
   End If
  Else
   obj.FromCurrency 1 - n
  End If
 Else
  obj.FromCurrency 1 - n
 End If
Case "IsNthPower"
 Set obj = objTarget.Clone
 Set objConst2 = New iValue
 objConst2.FromCurrency 1
 objConst2.OperatorDivideEqual objConst
 If obj.OperatorExpEqual(objConst2) Then
  If obj.ConvertTo(IValue_Integer) Then
   obj.FromCurrency 1
  Else
   obj.FromCurrency 0
  End If
 Else
  obj.FromCurrency 0
 End If
End Select
Set Apply = obj
End Function

'FIXME: check prime for bigger number
Friend Function IsPrime(ByVal n As Long) As Boolean
Dim p As Long, d As Long, m As Long
'///
If n <= 1 Then Exit Function
If n <= 3 Then
 IsPrime = True
 Exit Function
End If
If (n And 1&) = 0 Then Exit Function
If n Mod 3 = 0 Then Exit Function
'///starting from 5
p = 5
d = 2
m = Sqr(n) + 1
Do While p <= m
 If n Mod p = 0 Then Exit Function
 p = p + d
 d = 6 - d
Loop
IsPrime = True
End Function

Friend Sub Draw(ByVal bm As cAlphaDibSection, ByVal nLeft As Long, ByVal nTop As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal nColor As Long, ByVal objConst As iValue, ByVal objConst2 As iValue, Optional ByVal sFormat As String)
On Error Resume Next
Dim s As String, s2 As String
Dim f As Double
'///
If objConst Is Nothing Then Exit Sub
'///
Select Case m_t.sType
Case ":=": s = objText.GetText("set to")
Case "+": s = "+"
Case "-": s = ChrW(&H2212&)
Case "*": s = ChrW(&HD7&)
Case "/": s = ChrW(&HF7&)
Case "<": s = "<"
Case "=": s = "="
Case ">": s = ">"
Case "<=": s = ChrW(&H2264&)
Case ">=": s = ChrW(&H2265&)
Case "<>": s = ChrW(&H2260&)
Case "Mod": s = "mod"
Case "Abs"
 DrawTextAccordingToSize bm.hdc, "|" + ChrW(&H25A1&) + "|", nLeft, nTop, nWidth, nHeight, nColor
 Exit Sub
Case "IsPrime", "IsNotPrime"
 Select Case m_t.sType
 Case "IsPrime": s = objText.GetText("is prime")
 Case "IsNotPrime": s = objText.GetText("is not prime")
 End Select
 DrawTextAccordingToSize bm.hdc, s, nLeft, nTop, nWidth, nHeight, nColor
 Exit Sub
Case "IsNthPower"
 f = objConst.ToDouble
 Select Case f
 Case 2
  s = objText.GetText("is a square")
 Case 3
  s = objText.GetText("is a cube")
 Case Else
  s = Replace(objText.GetText("is a %sth power"), "%s", CStr(f))
 End Select
 DrawTextAccordingToSize bm.hdc, s, nLeft, nTop, nWidth, nHeight, nColor
 Exit Sub
Case "^", "Exp", "Log"
 s = objConst.ToString
 Select Case m_t.sType
 Case "^"
  s2 = ToSuperscript(s)
  If Len(s) = Len(s2) Then
   s = ChrW(&H25A1&) + s2
  Else
   If InStr(1, s, "+") > 0 Or InStr(1, s, "-") > 0 Or InStr(1, s, "/") > 0 Then
    s = "(" + s + ")"
   End If
   s = ChrW(&H25A1&) + "^" + s
  End If
 Case "Exp"
  If InStr(1, s, "+") > 0 Or InStr(1, s, "-") > 0 Or InStr(1, s, "/") > 0 Then
   s = "(" + s + ")"
  End If
  s = s + "^" + ChrW(&H25A1&)
 Case "Log"
  s2 = ToSubscript(s)
  If Len(s) = Len(s2) Then
   s = "log" + s2 + ChrW(&H25A1&)
  Else
   If InStr(1, s, "+") > 0 Or InStr(1, s, "-") > 0 Or InStr(1, s, "/") > 0 Then
    s = "(" + s + ")"
   End If
   s = "log_" + s + "(" + ChrW(&H25A1&) + ")"
  End If
 End Select
 DrawTextAccordingToSize bm.hdc, s, nLeft, nTop, nWidth, nHeight, nColor
 Exit Sub
Case "Log2"
 s = "log_" + ChrW(&H25A1&) + "(" + objConst.ToString + ")"
 DrawTextAccordingToSize bm.hdc, s, nLeft, nTop, nWidth, nHeight, nColor
 Exit Sub
Case "=Mod"
 If objConst2 Is Nothing Then Exit Sub
 DrawTextAccordingToSize bm.hdc, ChrW(&H2261&) + " " + objConst.ToString, nLeft, nTop, nWidth, nHeight \ 2, nColor
 DrawTextAccordingToSize bm.hdc, "mod " + objConst2.ToString, nLeft, nTop + nHeight \ 2, nWidth, nHeight \ 2, nColor
 Exit Sub
Case "<>Mod"
 If objConst2 Is Nothing Then Exit Sub
 DrawTextAccordingToSize bm.hdc, ChrW(&H2262&) + " " + objConst.ToString, nLeft, nTop, nWidth, nHeight \ 2, nColor
 DrawTextAccordingToSize bm.hdc, "mod " + objConst2.ToString, nLeft, nTop + nHeight \ 2, nWidth, nHeight \ 2, nColor
 Exit Sub
End Select
DrawTextAccordingToSize bm.hdc, s, nLeft, nTop, nWidth, nHeight \ 3, nColor
objConst.Draw bm, nLeft, nTop + nHeight \ 4, nWidth, nHeight - nHeight \ 4, nColor, sFormat
End Sub

